package com.william.jdbcplus.boot.test.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.william.jdbcplus.boot.starter.constant.DataSourceConstant;
import com.william.jdbcplus.boot.starter.interceptor.JdbcPlusInterceptor;
import com.william.jdbcplus.boot.starter.service.IService;
import com.william.jdbcplus.boot.starter.service.impl.ServiceImpl;
import com.william.jdbcplus.core.crud.CrudConfig;
import com.william.jdbcplus.core.crud.IBaseCrud;
import com.william.jdbcplus.core.crud.impl.BaseCrud;
import com.william.jdbcplus.core.dao.IBaseDao;
import com.william.jdbcplus.core.dao.impl.BaseDaoImpl;
import com.william.jdbcplus.core.ds.DynamicDataSource;
import com.william.jdbcplus.core.interceptor.JdkProxyHandler;
import com.william.jdbcplus.core.meta.TableHelperUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * @author niliwei
 */
@Configuration
@Slf4j
public class JdbcPlusConfig {

    @Value("${jdbc-plus.entity-package}")
    private String entityPackage;

    @Bean(name = DataSourceConstant.DYNAMIC)
    public DynamicDataSource dynamicDataSourceBean(@Qualifier(DataSourceConstant.MASTER) DruidDataSource druidDataSource) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setDefaultTargetDataSource(druidDataSource);
        Map<String, DruidDataSource> targetDataSources = new HashMap<>();
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }

    @Bean(name = "jdbcTemplate")
    public JdbcTemplate jdbcTemplateBean(@Qualifier(DataSourceConstant.DYNAMIC) DynamicDataSource ds) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(ds);
        return jdbcTemplate;
    }

    @Bean(name = "namedParameterJdbcTemplate")
    public NamedParameterJdbcTemplate namedParameterJdbcTemplate(@Qualifier("jdbcTemplate") JdbcTemplate jdbcTemplate) {
        NamedParameterJdbcTemplate jdbcOpt = new NamedParameterJdbcTemplate(jdbcTemplate);
        return jdbcOpt;
    }

    @Bean
    public CrudConfig getCrudConfig(@Qualifier("namedParameterJdbcTemplate") NamedParameterJdbcTemplate jdbcOpt, @Qualifier("jdbcTemplate") JdbcTemplate jdbcTemplate, RedisTemplate<String, Object> redisTemplate, RedisLockRegistry redisLock) {
        CrudConfig config = new CrudConfig(jdbcTemplate, jdbcOpt, redisTemplate, redisLock);
        return config;
    }

    /**
     * 动态代理 BaseCrud, 绑定自定义拦截器
     *
     * @return
     */
    @Bean
    public IBaseCrud getBaseCrud() {
        IBaseCrud proxy = (IBaseCrud) JdkProxyHandler.bind(new BaseCrud(), new JdbcPlusInterceptor());
        return proxy;
    }

    @Bean
    public IBaseDao getBaseDao(IBaseCrud baseCrud, CrudConfig config) {
        IBaseDao baseDao = new BaseDaoImpl(config, baseCrud);
        return baseDao;
    }

    @Bean
    public IService getService(IBaseDao baseDao) {
        IService service = new ServiceImpl(baseDao);
        return service;
    }

    @Bean
    public TableHelperUtil getTableHelper() {
        return new TableHelperUtil(entityPackage);
    }
}
